package com.sxbbc.common.basics.service.exception;

import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.InputMismatchException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.http.HttpStatus;
import org.springframework.messaging.handler.annotation.support.MethodArgumentTypeMismatchException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import com.function.common.GetRest;
import com.function.common.RestResponse;
import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.exceptions.ThrowPageException;

import common.Logger;

/**
 * 全局异常处理
 *
 * @author arno
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static Logger logger = Logger.getLogger(GlobalExceptionHandler.class);

    /**
     * 日期转换
     *
     * @param binder
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });
        binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        });
        binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
        });
    }

    @ExceptionHandler(value = ArithmeticException.class)
    @ResponseBody
    public RestResponse typeError(HttpServletRequest req, Exception e) {
        logger.info("ArithmeticException异常" + e.getMessage());
        return GetRest.getFail("参数类型错误");
    }

    @ExceptionHandler(value = IllegalArgumentException.class)
    @ResponseBody
    public RestResponse paramsError(HttpServletRequest req, Exception e) {
        logger.info("IllegalArgumentException异常" + e.getMessage());
        return GetRest.getFail("请求参数错误");
    }

    @ExceptionHandler(value = ClassNotFoundException.class)
    @ResponseBody
    public RestResponse classError(HttpServletRequest req, Exception e) {
        logger.info("ClassNotFoundException异常" + e.getMessage());
        return GetRest.getFail("文件丢失错误");
    }

    @ExceptionHandler(value = ArrayIndexOutOfBoundsException.class)
    @ResponseBody
    public RestResponse arrayError(HttpServletRequest req, Exception e) {
        logger.info("ArrayIndexOutOfBoundsException异常" + e.getMessage());
        return GetRest.getFail("数组溢出错误");
    }

    @ExceptionHandler(value = InputMismatchException.class)
    @ResponseBody
    public RestResponse inputError(HttpServletRequest req, Exception e) {
        logger.info("InputMismatchException异常" + e.getMessage());
        return GetRest.getFail("接收数据类型错误");
    }

    @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, NumberFormatException.class})
    @ResponseBody
    public RestResponse numberError(HttpServletRequest req, Exception e) {
        logger.info("MethodArgumentTypeMismatchException,NumberFormatException异常" + e.getMessage());
        return GetRest.getFail("数据格式化异常");
    }

    @ExceptionHandler(value = {IOException.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestResponse exception(Exception exception) {
        logger.info("IOException异常" + exception.getMessage());
        return GetRest.getFail("流处理异常");
    }

    /**
     * 处理所有业务异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ThrowJsonException.class)
    @ResponseBody
    public RestResponse handleBusinessException(ThrowJsonException e) {
        switch (e.getMessage()) {
            case "997":
                return GetRest.getFail("Token can't be Null", null, "997");
            case "998":
                return GetRest.getFail("Logon information error", null, "998");
            case "999":
                return GetRest.getFail("Unique primary can't be Null", null, "999");
            case "1000":
                return GetRest.getFail("登录已过期或在其他平台登陆", null, "1000");
            default:
                return GetRest.getFail(e.getMessage());
        }
    }

    /**
     * 处理所有业务异常
     *
     * @param
     * @return
     */
    @ExceptionHandler(ThrowPageException.class)
    @ResponseBody
    public ModelAndView showPageException(ThrowPageException e) {
        ModelAndView view = new ModelAndView("/exception");
        return view;
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public RestResponse errorResponse(HttpServletRequest req, Exception e) {
        logger.info("Exception异常：" + e.getMessage());
        e.printStackTrace();
        return GetRest.getFail("请求错误");
    }
}